package com.glsc.ngateway.platform.service.dev;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.glsc.ngateway.common.api.common.enums.Constant;
import com.glsc.ngateway.common.api.common.enums.DictConstant;
import com.glsc.ngateway.common.api.common.enums.PlatformConstant;
import com.glsc.ngateway.common.api.common.utils.PageUtil;
import com.glsc.ngateway.common.api.flowable.dto.FlowDoTaskRespDto;
import com.glsc.ngateway.common.api.flowable.dto.FlowParamAuthDto;
import com.glsc.ngateway.common.api.flowable.dto.FlowStartupFormDto;
import com.glsc.ngateway.common.api.flowable.dto.param.ParamCreateDto;
import com.glsc.ngateway.common.api.flowable.dto.param.ParamDeleteDto;
import com.glsc.ngateway.common.api.flowable.dto.param.ParamDoTaskDto;
import com.glsc.ngateway.common.api.flowable.dto.param.ParamRollbackDto;
import com.glsc.ngateway.common.api.flowable.dto.task.config.ProcessEditConfigDto;
import com.glsc.ngateway.common.api.flowable.feign.IFeignFlowableService;
import com.glsc.ngateway.common.api.flowable.resp.FlowableResponse;
import com.glsc.ngateway.common.api.flowable.resp.ResponseCreateDto;
import com.glsc.ngateway.common.api.flowable.resp.ResponseMsgDto;
import com.glsc.ngateway.common.api.flowable.resp.ResponseSituationDto;
import com.glsc.ngateway.common.api.platform.dto.user.PlatformUserDto;
import com.glsc.ngateway.common.api.shortmsg.bo.MessageGenericVo;
import com.glsc.ngateway.common.api.shortmsg.feign.IFeignShortmsgService;
import com.glsc.ngateway.common.base.domain.mysql.gateway.other.SystemConfig;
import com.glsc.ngateway.common.base.domain.mysql.gateway.platform.Appendix;
import com.glsc.ngateway.common.base.domain.mysql.gateway.platform.User;
import com.glsc.ngateway.common.base.domain.mysql.gateway.system.VEhrAdminStaff;
import com.glsc.ngateway.common.base.exception.PlatformException;
import com.glsc.ngateway.common.base.repo.mysql.gateway.platform.AppendixRepo;
import com.glsc.ngateway.common.base.repo.mysql.gateway.platform.system.VEhrAdminStaffRepository;
import com.glsc.ngateway.platform.aspect.UserCache;
import com.glsc.ngateway.platform.domain.*;
import com.glsc.ngateway.platform.dto.*;
import com.glsc.ngateway.platform.repo.*;
import com.glsc.ngateway.platform.service.FlowCommonService;
import com.glsc.ngateway.platform.service.MailService;
import com.glsc.ngateway.platform.service.SystemConfigService;
import com.glsc.ngateway.platform.service.UserService;
import com.glsc.ngateway.platform.service.itflow.config.ProcessEditConfigService;
import com.glsc.ngateway.platform.service.system.SystemMainService;
import com.glsc.ngateway.platform.utils.AssertOverride;
import com.glsc.ngateway.platform.utils.DateUtils;
import com.glsc.ngateway.platform.utils.JsonTool;
import com.glsc.ngateway.platform.utils.report.ReportFileConfigEnum;
import com.glsc.ngateway.platform.utils.report.ReportFileUtil;
import com.glsc.ngateway.platform.utils.report.ReportUploadContext;
import com.google.common.collect.Maps;
import org.apache.logging.log4j.util.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.glsc.ngateway.common.api.common.enums.PlatformConstant.*;

/**
 * @author guoj
 * @description: 测试任务管理
 * @date 2024/7/9 16:54
 */
@Service
public class TestTaskService {
    private static final Logger logger = LoggerFactory.getLogger(TestTaskService.class);
    @Resource
    private TestTaskRepository testTaskRepo;
    @Resource
    private DevManageRepository devManageRepository;
    @Resource
    private UserService userService;
    @Resource
    private MailService mailService;
    @Resource
    private UserCache userCache;
    @Resource
    private IFeignFlowableService feignFlowableService;
    @Resource
    private FlowCommonService flowCommonService;
    @Resource
    private RequirementTeskCaseRepo requirementTeskCaseRepo;
    @Resource
    @Qualifier("transactionManagerMysql")
    private PlatformTransactionManager transactionManager;
    @Resource
    private ProcessEditConfigService processEditConfigService;
    @Resource
    private AppendixRepo appendixRepo;
    @Resource
    private DevTaskDetailRepository devTaskDetailRepository;
    @Resource
    private SystemConfigService systemConfigService;
    @Resource
    private SystemMainService systemMainService;
    @Resource
    private IFeignShortmsgService iFeignShortmsgService;
    @Resource
    private DevManageService devManageService;
    @Resource
    private VEhrAdminStaffRepository vEhrAdminStaffRepository;
    @Resource
    private TestRelateRequirementRepository testRelateRequirementRepository;

    @Value("${wechat.url}")
    private String weChatUrl;
    

    public Page<TestTask> findPage(TestTaskDto paramSearchDto, HttpServletRequest request, String account) {
        logger.info("分页条件查询测试信息");
        LocalDateTime start = DateUtils.formatDateToLocalDateTime(DateUtils.formatDateString_(paramSearchDto.getCreateStart()));
        LocalDateTime end = DateUtils.formatDateToLocalDateTime(DateUtils.formatDateString_(paramSearchDto.getCreateEnd()));
        if (end != null) {
            end = end.plusDays(1);
        }

        paramSearchDto.setBeginDateLocalDate(start);
        paramSearchDto.setEndDateLocalDate(end);

        if (StrUtil.isNotEmpty(paramSearchDto.getSystemCode())) {
            paramSearchDto.setSystemCodes(Arrays.asList(paramSearchDto.getSystemCode().split(",")));
            paramSearchDto.setSystemCode(null);
        }

        Integer pageNo = PageUtil.initPageNo(paramSearchDto.getPageNo());
        Integer pageSize = PageUtil.initPageSize(paramSearchDto.getPageSize());
        Pageable pageable = PageRequest.of(pageNo - 1, pageSize);

        FlowParamAuthDto authCondition = new FlowParamAuthDto();
        //查询管理有多少人员，以查出人员在改善流程里的事件
        List<VEhrAdminStaff> staffs = vEhrAdminStaffRepository.findAllByReportTo(account);
        //分配给测试的人也可以看需求，开发人员
        List<RequirementTeskCase> teskCases = requirementTeskCaseRepo.findAllByOperator(account);
        List<String> processIds = teskCases.stream().map(e -> e.getProcessId()).collect(Collectors.toList());
        authCondition.setProcessIds(processIds);
        if (!userService.userRoleContain(Constant.DEV_ADMIN, account)) {
            authCondition.setAdmin("0");
        }

        //查关联的需求标题
        if (StrUtil.isNotEmpty(paramSearchDto.getRequirementTitle())){
            List<FlowFormTestRelateRequirement> relates = testRelateRequirementRepository.findAllByRequirementTitleLike("%"+paramSearchDto.getRequirementTitle()+"%");
            List<String> testProcessIds = relates.stream().filter(t->StrUtil.isNotEmpty(t.getProcessId())).map(e -> e.getProcessId()).collect(Collectors.toList());
            paramSearchDto.setRequireProcessIds(testProcessIds);
        }



        Page<TestTask> ret = testTaskRepo.searchByParam(pageable, paramSearchDto,authCondition,staffs);

        List<TestTask> content = ret.getContent();
        List<ResponseTestTaskDto> result = new ArrayList<>();
        if(CollectionUtil.isNotEmpty(content)){
            for (TestTask testTaskTemp : content) {
                ResponseTestTaskDto toResult = new ResponseTestTaskDto();
                FlowableResponse<ResponseSituationDto> processInfo = feignFlowableService.getProcessInfo(testTaskTemp.getProcessId());
                ResponseSituationDto data = processInfo.getData();
                BeanUtil.copyProperties(data, toResult);
                BeanUtil.copyProperties(testTaskTemp, toResult);
                result.add(toResult);
            }
        }
        return new PageImpl(result, pageable, ret.getTotalElements());
    }

    /**
     * 开发者发起流程
     * @param testTaskFormDto
     * @param operatorStart
     * @return
     */
    public FlowDoTaskRespDto createFlow(TestTaskFormDto testTaskFormDto, String operatorStart) {
        TestTask flowableFormData = testTaskFormDto.getFlowableFormData();
        if (ObjectUtil.isNull(testTaskFormDto)
                //测试用例必传
                //|| ObjectUtil.isNull(flowableFormData.getTestCaseList())
                || StrUtil.isEmpty(flowableFormData.getSystemManager())
//                || StrUtil.isEmpty(flowableFormData.getRequirementManager())
                || StrUtil.isEmpty(operatorStart)) {
            if (StrUtil.isBlank(testTaskFormDto.getCreateToTaskDefinitionKey())){
                throw PlatformException.errorWithOutMail("流程创建必填要素不能为空");
            }
        }
        PlatformUserDto createUser = userCache.get(operatorStart);
        testTaskFormDto.getFlowableFormData().setFlowCreatorDepartment(createUser.getDepartment());
        //【流程节点】，发起时动态指定节点处理人，
        Map<String, String> taskAssignee = new HashMap<>();
        if (StrUtil.isBlank(testTaskFormDto.getCreateToTaskDefinitionKey())) {
            taskAssignee = this.initTaskAssignee(testTaskFormDto);
        }

        //【流程节点变量】
        Map<String, String> conditionalVariable = new HashMap<>();

        TransactionStatus status = null;
        FlowDoTaskRespDto createFlowResponse = null;
        int flowException = 0;
        try {
            // 事务定义
            DefaultTransactionDefinition def = new DefaultTransactionDefinition();
            // 每次都开启一个新事务
            def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
            // 获取事务状态
            status = transactionManager.getTransaction(def);

            //2.表单内容（发起流程，表单内容为辅助）
            FlowStartupFormDto formDto = new FlowStartupFormDto();
            formDto.setTitle(flowableFormData.getProcessTitle());
            formDto.setComment("XX");//发起备注
            String flowCreateOperatorAccount = flowableFormData.getFlowCreateOperatorAccount();
            formDto.setCreatorId(flowCreateOperatorAccount);
            formDto.setCreatorName(flowableFormData.getFlowCreateOperatorName());


            ParamCreateDto paramCreateDto = new ParamCreateDto();
            paramCreateDto.setSysid(PlatformConstant.SYS_ID_GATEWAY);
            paramCreateDto.setProcessDefinitionKey(PlatformConstant.IT_TEST_TASK);
            paramCreateDto.setUserid(flowCreateOperatorAccount);//【重要！】这字段标识发起人！！！
            paramCreateDto.setContent(JSONObject.toJSON(formDto).toString());//纯粹为了flowable创建content需要一个JSON表单数据
            paramCreateDto.setTaskAssignee(taskAssignee);//各节点处理人
            paramCreateDto.setConditionalVariable(conditionalVariable);//控制流程节点变量
            paramCreateDto.setCreateComment(testTaskFormDto.getCommentDto().getFullMessage());

            //未启流程保存草稿时，CreateToTaskDefinitionKey变量为"beginTask"，流程引擎会在创建后调到初始节点
            if (StrUtil.isNotBlank(testTaskFormDto.getCreateToTaskDefinitionKey())) {
                paramCreateDto.setCreateToTaskDefinitionKey(testTaskFormDto.getCreateToTaskDefinitionKey());
            }
            createFlowResponse = new FlowDoTaskRespDto();
            //4.创建flowable流程
            FlowableResponse<ResponseCreateDto> createFlowableFlowResponse = feignFlowableService.create(paramCreateDto);
            if (createFlowableFlowResponse.getStatus() == 0) {
                createFlowResponse.setProcessId(createFlowableFlowResponse.getData().getProcessId());
                logger.info("流程关联，{}", createFlowResponse);
            } else {
                String errMsg = String.format("流程创建失败，{%s}，错误码={%s}-，原因：{%s}",
                        flowableFormData.getProcessTitle()
                        , createFlowableFlowResponse.getStatus(), createFlowableFlowResponse.getMsg());
                logger.error(errMsg);
                throw PlatformException.error(errMsg);
            }
            //保存测试任务 和用例
            saveTestTask(flowableFormData,createFlowResponse.getProcessId());

            //提交事务
            transactionManager.commit(status);
        } catch (Exception e) {
            flowException = 1;
            logger.info("异常，", e);
            String errMsg = "产品终止流程创建出现异常，回滚当前事务，原因:" + e.getMessage();
            if (status != null) {
                logger.info(errMsg);
                transactionManager.rollback(status);
            }
            //flowable回滚
            if (Objects.nonNull(createFlowResponse) && Objects.nonNull(createFlowResponse.getProcessId())) {
                logger.info("流程删除:" + createFlowResponse.getProcessId());
                feignFlowableService.deleteProcess(ParamDeleteDto.builder().processIdList(Collections.singletonList(createFlowResponse.getProcessId())).build());
            }
            throw PlatformException.error(errMsg);
        }finally {
            if (flowException==0 && StrUtil.isBlank(testTaskFormDto.getCreateToTaskDefinitionKey())){
                notify(flowableFormData, Arrays.asList(taskAssignee.get("uploadGroup").split(",")));
            }
        }
        return createFlowResponse;
    }


    /**
     * 保存测试任务 和 测试用例列表
     * @param flowableFormData
     * @param testProcessId
     */
    public void saveTestTask(TestTask flowableFormData,String testProcessId){
        TestTask toSave = flowableFormData;
        String flowCreateOperatorAccount = flowableFormData.getFlowCreateOperatorAccount();
        toSave.setFlowCreateOperatorAccount(flowCreateOperatorAccount);
        String flowCreatorDepartment = flowableFormData.getFlowCreatorDepartment();
        toSave.setFlowCreatorDepartment(flowCreatorDepartment);
        String flowCreateOperatorName = flowableFormData.getFlowCreateOperatorName();
        toSave.setFlowCreateOperatorName(flowCreateOperatorName);
        String systemManager = flowableFormData.getSystemManager();
        toSave.setRequirementManager(systemManager);
        toSave.setSystemManager(systemManager);
        toSave.setTestProcessStatus("进行中");
        toSave.setProcessId(testProcessId);
//        String requirementId = flowableFormData.getRequirementId();
//        toSave.setRequirementId(requirementId);
        toSave.setProcessTitle(flowableFormData.getProcessTitle());
        toSave.setProcessCreateTime(LocalDateTime.now());
//        toSave.setRequirementTitle(flowableFormData.getRequirementTitle());
        //保存测试任务和测试用例
        List<RequirementTeskCase> testCaseList = flowableFormData.getTestCaseList();
        if(CollectionUtil.isNotEmpty(testCaseList)){
            for(RequirementTeskCase  temp : testCaseList){
                temp.setFlowCreateOperatorAccount(flowCreateOperatorAccount);
                temp.setFlowCreatorDepartment(flowCreatorDepartment);
                temp.setFlowCreateOperatorName(flowCreateOperatorName);
                temp.setProcessId(testProcessId);
//                temp.setRequirementId(requirementId);
//                temp.setTestTaskId(saved.getId());
            }
//            requirementTeskCaseRepo.saveAll(testCaseList);
        }
        TestTask saved = testTaskRepo.save(toSave);

    }

    /**
     * 流程中保存实体的修改
     * @param testTaskFormDto
     * @param username
     */
    @Transactional
    public FlowDoTaskRespDto saveTestTaskAndTestCaseList(TestTaskFormDto testTaskFormDto,String username){
        if (ObjectUtil.isNull(testTaskFormDto)
                ||ObjectUtil.isNull(testTaskFormDto.getFlowableFormData())
                || StrUtil.isEmpty(username)) {
            throw PlatformException.error("流程保存必填要素不能为空");
        }

        FlowDoTaskRespDto respDto = null;
        if (StrUtil.isNotEmpty(testTaskFormDto.getTaskId())) {
            respDto = flowCommonService.validCheckTaskBeforeSaveFormOrAuditTask(testTaskFormDto.getTaskId());
        } else {
            respDto = new FlowDoTaskRespDto();
        }
        TestTask flowableFormData = testTaskFormDto.getFlowableFormData();
        if (StrUtil.isNotEmpty(respDto.getProcessId())) {
            flowableFormData.setProcessId(respDto.getProcessId());
        }
//        TestTask toSave = new TestTask();
//        BeanUtil.copyProperties(flowableFormData,toSave);
        List<RequirementTeskCase> DBCaseList = requirementTeskCaseRepo.queryByProcessIdAndTestTaskIdIsNotNull(respDto.getProcessId());
        List<Long> teatCaseIds = DBCaseList.stream().map(RequirementTeskCase::getId).collect(Collectors.toList());
        Map<Long,RequirementTeskCase> testCaseMapDB = DBCaseList.stream().collect(Collectors.toMap(RequirementTeskCase::getId,  task -> task));
        List<RequirementTeskCase> addCaseList = new ArrayList<>();
        List<RequirementTeskCase> testCaseList = flowableFormData.getTestCaseList();
        Map<Long,RequirementTeskCase> testCaseMap = testCaseList.stream().filter(e ->e.getId() != null).collect(Collectors.toMap(RequirementTeskCase::getId,  task -> task));
        String flowCreatorDepartment = flowableFormData.getFlowCreatorDepartment();
        String flowCreateOperatorName = flowableFormData.getFlowCreateOperatorName();
        String flowCreateOperatorAccount = flowableFormData.getFlowCreateOperatorAccount();
        if(CollectionUtil.isNotEmpty(testCaseList)){
            for(RequirementTeskCase  temp : testCaseList){
                temp.setFlowCreateOperatorAccount(flowCreateOperatorAccount);
                temp.setFlowCreatorDepartment(flowCreatorDepartment);
                temp.setFlowCreateOperatorName(flowCreateOperatorName);
                temp.setProcessId(respDto.getProcessId());
                //非自己的用例以数据库为准，避免被后来人修改
                if (testTaskFormDto.getTaskDefinitionKey().equals(IT_TESTTASK_NODE_TESTER) && temp.getId() != null
                        && !temp.getOperator().equals(username) && testCaseMapDB.keySet().contains(temp.getId())){
                    BeanUtil.copyProperties(testCaseMapDB.get(temp.getId()),temp);
                }
//                if (temp.getId() == null){
//                    addCaseList.add(temp);
//                }
//                if (temp.getId() != null && !teatCaseIds.contains(temp.getId())){
//                    throw PlatformException.errorWithOutMail("和已提交的测试用例存在冲突，请刷新后再提交");
//                }
//                if (temp.getId() != null){
//                    RequirementTeskCase dbValue = testCaseMapDB.get(temp.getId());
//                    if (!StrUtil.equals(dbValue.getCaseTitle(),temp.getCaseTitle())){
//                        throw PlatformException.errorWithOutMail(temp.getCaseTitle()+"和数据库值存在冲突，请刷新后再提交");
//                    }
//                    if (!StrUtil.equals(dbValue.getCaseContent(),temp.getCaseContent())){
//                        throw PlatformException.errorWithOutMail(temp.getCaseContent()+"和数据库值存在冲突，请刷新后再提交");
//                    }
//                }
//                temp.setRequirementId(toSave.getRequirementId());
//                temp.setTestTaskId(saved.getId());
            }
//            requirementTeskCaseRepo.saveAll(testCaseList);
        }
        if (testCaseMapDB != null && testCaseMap != null){
            if (testCaseMapDB.keySet().size() > testCaseMap.keySet().size()){
                //把数据库更新的数据放入bean中，做增量添加
                for(RequirementTeskCase db : DBCaseList){
                    if (!testCaseMap.keySet().contains(db.getId())){
                        addCaseList.add(db);
                    }
                }
//                    throw PlatformException.errorWithOutMail("存在新提交的测试用例冲突，请复制好已填写的测试用例，刷新后再填写提交");
            }
            testCaseList.addAll(addCaseList);
        }

        TestTask saved = testTaskRepo.save(flowableFormData);

        return respDto;
    }

    /**
     * 设置流程处理人
     * @param testCaseDto
     * @return
     */
    private Map<String, String> initTaskAssignee(TestTaskFormDto testCaseDto) {
        Map<String, String> taskAssignee = Maps.newHashMap();
        List<FlowFormTestRelateRequirement> req = testCaseDto.getFlowableFormData().getRequirementList();
        List<String> requireIdList = req.stream().map(FlowFormTestRelateRequirement::getRequirementId).collect(Collectors.toList());
        List<FlowFormTaskDetail> taskDetailList = devTaskDetailRepository.findAllByProcessIdIn(requireIdList);
        String taskAccount = taskDetailList.stream().map(FlowFormTaskDetail::getTaskPersonAccount).distinct().collect(Collectors.joining(","));
        taskAssignee.put("uploadGroup", taskAccount);
        taskAssignee.put("systemManagerGroup", testCaseDto.getFlowableFormData().getSystemManager());
        return taskAssignee;
    }

    /**
     * 导入测试用例
     * @param file
     * @return
     * @throws IOException
     */
    @Transactional
    public ReportUploadContext<UploadTestCaseDto, String> testCaseUpload(MultipartFile file) throws IOException {
        ReportUploadContext<UploadTestCaseDto, String> context = ReportUploadContext.<UploadTestCaseDto, String>builder()
                .config(ReportFileConfigEnum.TEST_CASE)
                .file(file)
                .check(this::checkTestCase)
                .build();
        ReportFileUtil.readSingleExcel(context);
        AssertOverride.notEmpty(context.getReadRes(), "上传内容不可为空");
        return context;
    }


    /**
     * 校验测试用例
     *
     * @param dto
     */
    public void checkTestCase(UploadTestCaseDto dto) {
        AssertOverride.isTrue(org.apache.commons.lang.StringUtils.isNotEmpty(dto.getCaseContent()), "[测试用例内容]不可为空");
        AssertOverride.isTrue(org.apache.commons.lang.StringUtils.isNotEmpty(dto.getCaseTitle()), "[测试用例标题]不可为空");
    }

    public FlowDoTaskRespDto taskAuditPass(TestTaskFormDto testTaskFormDto, String operatorStart) {
        if (ObjectUtil.isNull(testTaskFormDto)
                //测试用例必传
                //|| ObjectUtil.isNull(flowableFormData.getTestCaseList())
                || StrUtil.isEmpty(testTaskFormDto.getFlowableFormData().getSystemManager())
//                || StrUtil.isEmpty(flowableFormData.getRequirementManager())
                || StrUtil.isEmpty(operatorStart)) {
            throw PlatformException.errorWithOutMail("流程创建必填要素不能为空");
        }
        //【1.任务合法性数据】
        FlowDoTaskRespDto respDto = flowCommonService.validCheckTaskBeforeSaveFormOrAuditTask(testTaskFormDto.getTaskId());
        //根据查询出的节点类型赋值
        testTaskFormDto.setTaskDefinitionKey(respDto.getTaskDefinitionKey());
        //流程注入变量更新
        Map<String, String> taskAssignee = new HashMap<>();
        Map<String, String> conditionalVariable = new HashMap<>();
        //其他节点已在创建时指定
        if (IT_TESTTASK_NODE_BEGIN_TASK.equals(testTaskFormDto.getTaskDefinitionKey())){
            taskAssignee = this.initTaskAssignee(testTaskFormDto);
        } else if(IT_TESTTASK_NODE_SYSTEMMANAGER.equals(testTaskFormDto.getTaskDefinitionKey())){
            List<RequirementTeskCase> testCaseList = testTaskFormDto.getFlowableFormData().getTestCaseList();
            if (CollectionUtil.isEmpty(testCaseList)) {
                throw PlatformException.errorWithOutMail("未查询到测试用例");
            }
            Set<String> testcaseOperators = testCaseList.stream()
                    .map(RequirementTeskCase::getOperator)
                    .collect(Collectors.toSet());
            if(CollectionUtil.isEmpty(testcaseOperators)){
                throw PlatformException.errorWithOutMail("未分配测试用例操作人");
            }
            taskAssignee.put("testerGroup",String.join(",",testcaseOperators));
        } else if (IT_TESTTASK_NODE_TESTER.equals(testTaskFormDto.getTaskDefinitionKey())){
            taskAssignee.put("onlineGroup",testTaskFormDto.getFlowableFormData().getSystemManager());
            //自动填充测试时间
            List<RequirementTeskCase> testCaseList = testTaskFormDto.getFlowableFormData().getTestCaseList();
            for (RequirementTeskCase testCase :testCaseList){
                if (testCase.getOperator().equals(operatorStart)){
                    testCase.setTestPassTime(LocalDateTime.now());
                }
            }
        }else {
            // 处理未知或错误的任务节点
            logger.info("当前任务节点: {}", testTaskFormDto.getTaskDefinitionKey());
            // 可以选择抛出异常或进行其他错误处理
        }

        //审核事务通过
        TransactionStatus status = null;
        int flowException = 0;
        try {
            // 事务定义
            DefaultTransactionDefinition def = new DefaultTransactionDefinition();
            // 每次都开启一个新事务
            def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
            // 获取事务状态
            status = transactionManager.getTransaction(def);

            //保存表单数据
            FlowDoTaskRespDto saveRespDto = this.saveTestTaskAndTestCaseList(testTaskFormDto, operatorStart);
            if (saveRespDto == null) {
                throw PlatformException.error("保存表单数据失败");
            }

            ParamDoTaskDto paramDotaskDto = new ParamDoTaskDto();
            paramDotaskDto.setSysid(PlatformConstant.SYS_ID_GATEWAY);
            paramDotaskDto.setTaskId(testTaskFormDto.getTaskId());
            paramDotaskDto.setComment(flowCommonService.initCommentDto(testTaskFormDto.getCommentDto()));
            paramDotaskDto.setTitle("");
            paramDotaskDto.setContent(JsonTool.objectToJson(paramDotaskDto));//flowable网关保存每次审批的全量数据
            paramDotaskDto.setTaskAssignee(taskAssignee);
            paramDotaskDto.setConditionalVariable(conditionalVariable);
            paramDotaskDto.setComment(testTaskFormDto.getCommentDto());

            //自动通过需求流程里的等待上线节点
            if (IT_TESTTASK_NODE_ONLINE_TASK.equals(testTaskFormDto.getTaskDefinitionKey())){
                List<FlowFormTestRelateRequirement> requieList = testTaskFormDto.getFlowableFormData().getRequirementList();
                for (FlowFormTestRelateRequirement requirement : requieList) {
                    FlowableResponse<ResponseSituationDto> processInfo = feignFlowableService.getProcessInfo(requirement.getRequirementId());
                    if (IT_DEV_MANAGE_NODE_WAIT_ONLINE_TASK.equals(processInfo.getData().getCurrentTaskDefinitionKey())) {
                        DevManageDto taskDto = new DevManageDto();
                        taskDto.setTaskId(processInfo.getData().getCurrentTaskId());
                        DevManageDto devManageDto = devManageService.getWorkFlowFormByTaskId(taskDto);
                        devManageService.taskAuditPass(devManageDto,"admin");
                    }
                }
            }


            //调用网关审核，注意前面表单的保存与这里审批通过，事物可能不一致，暂时不予处理这种不一致的情况
            FlowableResponse<ResponseMsgDto> flowableResponse = flowCommonService.taskAuditPass(paramDotaskDto);
            if (0 == flowableResponse.getStatus()) {
                //提交事务
                transactionManager.commit(status);
               
                return respDto;
            } else {
                String errMsg = "流程审核失败，错误码" + flowableResponse.getStatus() + "，原因：" + flowableResponse.getMsg() + "，详情：" + flowableResponse.getData();
                logger.error(errMsg);
                throw PlatformException.error(errMsg);
            }
        } catch (Exception e) {
            flowException = 1;
            if (status != null && !status.isCompleted()) {
                logger.error("事务事件流程创建出现异常，回滚当前事务");
                transactionManager.rollback(status);
            } else {
                logger.error("事务事件出现异常，transaction def status is null");
            }
            mailService.sendMailToAdminWithOutDB("测试流程审核异常", e.getMessage());
            throw e;
        } finally {
            //发送邮件和微信通知
            if (flowException == 0 && CollectionUtil.isNotEmpty(taskAssignee.values())){
                for(String accounts : taskAssignee.values()){
                    //todo
                    notify(testTaskFormDto.getFlowableFormData(),Arrays.asList(accounts.split(",")));
                }
            }
        }
    }

    public void notify(@NotNull TestTask formDevManage, List<String> notifyAccount) {
        String[] mailList = userService.findAllByAccountList(notifyAccount).stream().map(User::getEmail).toArray(String[]::new);;
        SystemConfig agentIdConfig = systemConfigService.findByCode("WECHAT_GATEWAY_APP_AGENTID");
        boolean hasAgentIdConfig = Objects.nonNull(agentIdConfig) && Strings.isNotBlank(agentIdConfig.getConfigValue());
        //邮件通知
        String title = String.format("【测试流程】-【节点审核】-【%s】", formDevManage.getProcessTitle());
        String content = String.format("测试标题：%s<br/>  发起人：%s<br/>  所属系统：%s<br/>   请知悉。可至国联技术服务平台内查阅相关事宜。"
                , formDevManage.getProcessTitle()
                , formDevManage.getFlowCreateOperatorName()
                , Optional.ofNullable(systemMainService.findBySystemClassNo(formDevManage.getSystemCode()))
                        .orElseThrow(() -> PlatformException.error("未找到系统：" + formDevManage.getSystemCode())).getOpName()
//                , userCache.get(formDevManage.getSystemAdminAccount()).getName()
//                , (Objects.isNull(formDevManage.getEventGrade()) ? "无" :
//                        Optional.ofNullable(dictionaryService.findByDictEntryAndDictSubentry("event_manage_grade", formDevManage.getEventGrade()))
//                                .orElseThrow(() -> PlatformException.error("未找到字典项：event_manage_grade， " + formDevManage.getEventGrade())).getDictValue())
//                , (Objects.isNull(formDevManage.getEventClass()) ? "无" :
//                        Optional.ofNullable(dictionaryService.findByDictEntryAndDictSubentry("event_manage_class", formDevManage.getEventClass()))
//                                .orElseThrow(() -> PlatformException.error("未找到字典项：event_manage_class， " + formDevManage.getEventClass())).getDictValue())
//                , formDevManage.getDemandSummary() != null && formDevManage.getDemandSummary().length() > 500 ? formDevManage.getDemandSummary().substring(0, 500) + "..." : formDevManage.getDemandSummary()
        );
//        LocalDateTime referenceDateTime = LocalDateTime.of(2024, Month.MAY,10,18,00); // 这里时间为 20240510
//        if ((formDevManage.getInsertTime() != null && formDevManage.getInsertTime().isAfter(referenceDateTime)) || systemConfigService.findByCode("NEW_EVENT_NOTIFY") != null ){
            mailService.sendMail(mailList, null, title
                    , DictConstant.TODO_LINK
                    , title, content, null, Constant.MAIL_TYPE_IT_FLOW
            );
            if (hasAgentIdConfig) {
                iFeignShortmsgService.sendAgentMessageGeneric(MessageGenericVo.builder()
                        .oaUserAccounts(notifyAccount)
                        .agentId(agentIdConfig.getConfigValue())
                        .textContent("<br><a href='" + weChatUrl + "'>" + title + "</a>" +
                                "<br>  " + content)
                        .build());
            }
//        }
    }


    /**
     * 根据流程实例ID或者任务ID检索流程
     *
     */
    public TestTaskFormDto getWorkFlowFormByTaskId(TestTaskFormDto testTaskFormDto) {
        if (testTaskFormDto == null || StrUtil.isEmpty(testTaskFormDto.getTaskId()) && StrUtil.isEmpty(testTaskFormDto.getProcessId())) {
            throw PlatformException.error("查询产品终止流程时，需要提供流程实例Id或者任务Id和流程节点标识");
        }

        TestTaskFormDto respDto = new TestTaskFormDto();


        ResponseSituationDto currentTaskInfo = null;
        if (StrUtil.isEmpty(testTaskFormDto.getTaskId())) {//流程结束或者抄送查看流程时，仅根据processId检索要素信息
            respDto.setProcessId(testTaskFormDto.getProcessId());
            respDto.setHandleProcessMode(PlatformConstant.FLOWABLE_HANDLE_MODE_VIEW);
            respDto.setCurrentTaskInfo(new ResponseSituationDto());//减轻前段判空处理
        } else {
            testTaskFormDto.setTaskId(StrUtil.trim(testTaskFormDto.getTaskId()));
            respDto.setHandleProcessMode(PlatformConstant.FLOWABLE_HANDLE_MODE_EDIT);
            FlowableResponse<ResponseSituationDto> flowableTaskInfoResponse = flowCommonService.getTaskInfo(testTaskFormDto.getTaskId()
                    , PlatformConstant.SYS_ID_GATEWAY);
            if (flowableTaskInfoResponse.getStatus() != 0) {
                throw PlatformException.error("流程引擎未查询到任务信息" + testTaskFormDto.getTaskId());
            } else {
                testTaskFormDto.setProcessId(flowableTaskInfoResponse.getData().getProcessId());//后续保存策略会用到processId
                currentTaskInfo = flowableTaskInfoResponse.getData();
                respDto.setCurrentTaskInfo(currentTaskInfo);//task 任务详情
                respDto.setProcessId(currentTaskInfo.getProcessId());
                respDto.setTaskId(currentTaskInfo.getCurrentTaskId());//具体任务方式查看，需要taskId/taskDefinitionKey
                respDto.setTaskDefinitionKey(currentTaskInfo.getCurrentTaskDefinitionKey());
                respDto.setProcessDefineKey(currentTaskInfo.getProcessDefineKey());

                //加载任务节点信息
                ProcessEditConfigDto editConfigDto = processEditConfigService.getProcessEditConfigDto(respDto.getProcessDefineKey(), respDto.getTaskDefinitionKey());
                respDto.setProcessEditConfigDto(editConfigDto);
            }
        }

        //查询表单数据
        TestTask flowFormTestTask = this.findFormByProcessId(respDto.getProcessId());
        respDto.setFlowableFormData(flowFormTestTask);

        return respDto;
    }

    /**
     * 测试用例中的 oa账户——》 名字
     * @param processId
     * @return
     */
    private TestTask findFormByProcessId(String processId) {
//        List<RequirementTeskCase> rtcList = requirementTeskCaseRepo.queryByProcessId(processId);
        TestTask testTask = testTaskRepo.queryByProcessId(processId);
        if (testTask != null && StrUtil.isNotBlank(testTask.getDemandOnlineDocIdList())) {
            String[] docIds = testTask.getDemandOnlineDocIdList().split(",");
            List<Appendix> docList = new ArrayList<>();
            if (docIds != null && docIds.length > 0) {
                for (String docId : docIds) {
                    Appendix appendix = appendixRepo.findById(docId);
                    docList.add(appendix);
                }
            }
            testTask.setDemandOnlineDocList(docList);
        }
        if (testTask != null && StrUtil.isNotBlank(testTask.getSonarDocIdList())) {
            String[] docIds = testTask.getSonarDocIdList().split(",");
            List<Appendix> docList = new ArrayList<>();
            if (docIds != null && docIds.length > 0) {
                for (String docId : docIds) {
                    Appendix appendix = appendixRepo.findById(docId);
                    docList.add(appendix);
                }
            }
            testTask.setSonarDocList(docList);
        }
        
//        FlowFormTestTask result = new FlowFormTestTask();
//        BeanUtil.copyProperties(testTask,result);
//        testTask.setTestCaseList(rtcList);
        return  testTask;
    }


    private Map<String,String> getUserAccount(List<RequirementTeskCase> content){
        Set<String> systemUserIdSet = content.stream()
                .filter(x -> Objects.nonNull(x.getOperator()))
                .map(RequirementTeskCase::getOperator)
                .collect(Collectors.toSet());
        List<String> systemUserIdList = new ArrayList<>();
        for (String systemUserIdTemp : systemUserIdSet) {
            if(StrUtil.isEmpty(systemUserIdTemp)){
                continue;
            }
            //多个责任人
            if(systemUserIdTemp.contains(",")){
                String[] split = systemUserIdTemp.split(",");
                systemUserIdList.addAll( Arrays.asList(split));
            }else{
                systemUserIdList.add(systemUserIdTemp);
            }
        }
        List<User> userList = userService.findAllByAccountList(systemUserIdList);
        return userList
                .stream()
                .collect(Collectors.toMap(User::getUsername, User::getName));
    }

    public FlowDoTaskRespDto taskAuditReject(TestTaskFormDto testTaskFormDto) {

        //【1.任务合法性数据】
        FlowDoTaskRespDto respDto = flowCommonService.validCheckTaskBeforeSaveFormOrAuditTask(testTaskFormDto.getTaskId());


        //【2.公共处理】检查文件必传性，zzp

        //【3.获取任务审核前的流程信息】
        ResponseSituationDto beforeAuditFlowInfo = flowCommonService.getProcessInfo(respDto.getProcessId());
        //END OF【公共处理】查询任务基础信息

        //各节点，驳回时，业务逻辑特殊处理

        ParamRollbackDto flowableTaskDto = new ParamRollbackDto();
        flowableTaskDto.setSysid(PlatformConstant.SYS_ID_GATEWAY);
        flowableTaskDto.setTaskId(testTaskFormDto.getTaskId());
        flowableTaskDto.setComment(flowCommonService.initCommentDto(testTaskFormDto.getCommentDto()).getFullMessage());
        flowableTaskDto.setTitle("XXXXX");
        flowableTaskDto.setContent(JsonTool.objectToJson(flowableTaskDto));
        //驳回时，要求提供title、comment
        flowableTaskDto.setComment(testTaskFormDto.getCommentDto().getFullMessage());

        FlowableResponse<FlowDoTaskRespDto> flowableResponse = flowCommonService.taskAuditReject(flowableTaskDto);
        if (0 == flowableResponse.getStatus()) {
            //流程回退成功,后续处理

            return flowableResponse.getData();
        } else {
            throw PlatformException.error("流程退回失败");
        }
    }
}
